home *** CD-ROM | disk | FTP | other *** search
/ Precision Software Appli…tions Silver Collection 1 / Precision Software Applications Silver Collection Volume One (PSM) (1993).iso / tutor / asm1tut.exe / CHAP10-2.DOC < prev    next >
Text File  |  1990-06-24  |  37KB  |  961 lines

  1.  
  2.  
  3.  
  4.              Chapter 10 - Templates                                         89
  5.              ______________________
  6.  
  7.              Do all three conditions need to be met for the linker to combine
  8.              segments into one segment? 
  9.  
  10.                  1)  They have the same name
  11.                  2)  They have the same class name
  12.                  3)  They are both defined PUBLIC
  13.  
  14.              Joe Bob says check it out. Here are two .ASM files which contain
  15.              a number of segments. Here's the first file:
  16.  
  17.                ;file1.asm 
  18.                ;- - - - - - - - - - - - - - - - - - - - 
  19.                STACKSEG    SEGMENT   STACK  'STACK' 
  20.                             dw     100 dup (?) 
  21.                STACKSEG    ENDS 
  22.                ;- - - - - - - - - - - - - - - - - - - - 
  23.                MORESTUFFA    SEGMENT   PUBLIC
  24.                variable21    dw     ? 
  25.                MORESTUFFA    ENDS 
  26.                ;- - - - - - - - - - - - - - - - - - - - 
  27.                DATASTUFF    SEGMENT   PUBLIC  'DATA' 
  28.                variable1    dw     ? 
  29.                DATASTUFF    ENDS 
  30.                ;- - - - - - - - - - - - - - - - - - - - 
  31.                MORESTUFF    SEGMENT   PUBLIC  'DATA' 
  32.                variable2    dw     ? 
  33.                MORESTUFF    ENDS 
  34.                ;- - - - - - - - - - - - - - - - - - - - 
  35.                EVENMORESTUFF    SEGMENT   PUBLIC  'DATA' 
  36.                variable3    dw     ? 
  37.                EVENMORESTUFF    ENDS 
  38.                ;- - - - - - - - - - - - - - - - - - - - 
  39.                CODESTUFF    SEGMENT   PUBLIC  'CODE' 
  40.                       ASSUME cs:CODESTUFF, ds:DATASTUFF 
  41.                       ASSUME ds:MORESTUFF, es:MORESTUFFA, ds:EVENMORESTUFF 
  42.                main   proc far 
  43.                start: push  ds           
  44.                       sub   ax,ax 
  45.                       push  ax 
  46.                       ret 
  47.                main   endp 
  48.                CODESTUFF    ENDS 
  49.                ;- - - - - - - - - - - - - - - - - - - - 
  50.                       END     start 
  51.                 
  52.              Here's the other file:
  53.  
  54.                ;file2.asm 
  55.                ; - - - - - - - - - - - - - - - - - - - - 
  56.                STACKSEG    SEGMENT   STACK  'STACK' 
  57.                             dw     100 dup (?) 
  58.                STACKSEG    ENDS 
  59.                ; - - - - - - - - - - - - - - - - - - - - 
  60.                NOTDATASTUFF    SEGMENT   PUBLIC  'DATA' 
  61.                variable4    dw     ? 
  62.                NOTDATASTUFF    ENDS 
  63.                ; - - - - - - - - - - - - - - - - - - - - 
  64.  
  65.  
  66.  
  67.  
  68.              The PC Assembler Tutor                                         90
  69.              ______________________
  70.  
  71.                DATASTUFF    SEGMENT   PUBLIC  'DATA' 
  72.                variable5    dw     ? 
  73.                DATASTUFF    ENDS 
  74.                ; - - - - - - - - - - - - - - - - - - - - 
  75.                MORESTUFFA    SEGMENT   PUBLIC  
  76.                variable61    dw     ? 
  77.                MORESTUFFA    ENDS 
  78.                ; - - - - - - - - - - - - - - - - - - - - 
  79.                MORESTUFF    SEGMENT   PUBLIC  'CLASSOF68' 
  80.                variable6    dw     ? 
  81.                MORESTUFF    ENDS 
  82.                ; - - - - - - - - - - - - - - - - - - - - 
  83.                EVENMORESTUFF    SEGMENT   'DATA' 
  84.                variable7    dw     ? 
  85.                EVENMORESTUFF    ENDS 
  86.                ; - - - - - - - - - - - - - - - - - - - - 
  87.                CODESTUFF    SEGMENT   PUBLIC  'CODE' 
  88.                 ASSUME cs:CODESTUFF, ds:DATASTUFF, ds:NOTDATASTUFF 
  89.                 ASSUME ds:MORESTUFF,ds:MORESTUFFA, ds:EVENMORESTUFF 
  90.                subroutine   proc far 
  91.                       ret 
  92.                subroutine    endp 
  93.                CODESTUFF    ENDS 
  94.                ; - - - - - - - - - - - - - - - - - - - - 
  95.                       END  
  96.                 
  97.  
  98.  
  99.              You will notice that the two CODESTUFFs, the two DATASTUFFs, the
  100.              two MORESTUFFAs and the two STACKSEGs each have the same
  101.              definitions, but that (1) NOTDATASTUFF has a different name than
  102.              DATASTUFF, (2) one MORESTUFF has a different class name from the
  103.              other, (3) one EVENMORESTUFF is PUBLIC and the other is not, and
  104.              (4) the two MORESTUFFAs have NO class name.
  105.  
  106.              Here's the segment information from file1.lst
  107.  
  108.  
  109.  
  110.                N a m e                       Length Align  Combine  Class
  111.  
  112.                CODESTUFF  . . . . . . . . . .  0005 PARA    PUBLIC  'CODE'
  113.                DATASTUFF  . . . . . . . . . .  0002 PARA    PUBLIC  'DATA'
  114.                EVENMORESTUFF  . . . . . . . .  0002 PARA    PUBLIC  'DATA'
  115.                MORESTUFF  . . . . . . . . . .  0002 PARA    PUBLIC  'DATA'
  116.                MORESTUFFA . . . . . . . . . .  0002 PARA    PUBLIC
  117.                STACKSEG . . . . . . . . . . .  00C8 PARA    STACK   'STACK'
  118.  
  119.  
  120.  
  121.  
  122.              and from file2.lst
  123.  
  124.  
  125.                N a m e                   Length Align  Combine  Class
  126.  
  127.                CODESTUFF  . . . . . . .   0001 PARA    PUBLIC  'CODE'
  128.  
  129.  
  130.  
  131.  
  132.              Chapter 10 - Templates                                         91
  133.              ______________________
  134.  
  135.                DATASTUFF  . . . . . . .   0002 PARA    PUBLIC  'DATA'
  136.                EVENMORESTUFF  . . . . .   0002 PARA    NONE    'DATA'
  137.                MORESTUFF  . . . . . . .   0002 PARA    PUBLIC  'CLASSOF68'
  138.                MORESTUFFA . . . . . . .   0002 PARA    PUBLIC
  139.                NOTDATASTUFF . . . . . .   0002 PARA    PUBLIC  'DATA'
  140.                STACKSEG . . . . . . . .   00C8 PARA    STACK   'STACK'
  141.  
  142.  
  143.  
  144.              These are in alphabetical order. Before we link them together,
  145.              let's think about what should happen if all three conditions must
  146.              be met. Both CODESTUFF segments are PUBLIC with the same class
  147.              name, so they should merge. Both DATASTUFF segments are PUBLIC
  148.              with the same class name so they should merge. EVENMORESTUFF is
  149.              PUBLIC in one file but not public in the other, so they should
  150.              not merge. MORESTUFF is PUBLIC in both files, but they have
  151.              different class names, so they should not merge. What about
  152.              STACKSEG? The STACK combine type is similar to PUBLIC{1}, and
  153.              they have the same class name, so they should merge. Finally,
  154.              there are the  MORESTUFFAs. They have the same name and are
  155.              PUBLIC, but they have no class name. Will they combine? 
  156.  
  157.              Let's see what happens. Here is the .MAP file from the command
  158.  
  159.                  C> link file1+file2
  160.  
  161.               
  162.                   Start  Stop   Length Name                   Class 
  163.                   00000H 0018FH 00190H STACKSEG               STACK 
  164.                   00190H 001A1H 00012H MORESTUFFA              
  165.                   001B0H 001C1H 00012H DATASTUFF              DATA 
  166.                   001D0H 001D1H 00002H MORESTUFF              DATA 
  167.                   001E0H 001E1H 00002H EVENMORESTUFF          DATA 
  168.                   001F0H 001F1H 00002H NOTDATASTUFF           DATA 
  169.                   00200H 00201H 00002H EVENMORESTUFF          DATA 
  170.                   00210H 00220H 00011H CODESTUFF              CODE 
  171.                   00230H 00231H 00002H MORESTUFF              CLASSOF68 
  172.               
  173.                  Program entry point at 0021:0000 
  174.  
  175.  
  176.              STACKSEG, DATASTUFF and CODESTUFF combined. MORESTUFFA combined.
  177.              The others are separate. Doesn't this confuse the linker if it
  178.              has more than one segment with the same name? No. The linker
  179.              knows which variables are in which segments, and the names of the
  180.              segments are not relevant. 
  181.  
  182.              If you look at the class information from the linker listing, you
  183.              will notice that all things in the same class are grouped
  184.              together. The linker works from left to right on the command
  185.              line, so for the above, it read file1.obj first and then read
  186.              ____________________
  187.  
  188.                 1 STACK tells the linker to combine any other segments which
  189.              have STACK and the class type 'STACK' and it tells the loader to
  190.              set the SS register to that segment, and set the SP register to
  191.              point to the end of that segment.
  192.  
  193.  
  194.  
  195.  
  196.              The PC Assembler Tutor                                         92
  197.              ______________________
  198.  
  199.              file2.obj. It orders things (1) first by class (in the order
  200.              encountered, and then (2) by segment (in the order encountered).
  201.              For the linker ordering, a segment is like a subclass. 
  202.  
  203.              Look through the assembler files to check that if you link in the
  204.              order file1+file2, the order of encountering classes is 'STACK',
  205.              empty, 'DATA', 'CODE', and 'CLASSOF68'. check the segment
  206.              ordering also. What if we link the opposite way?
  207.  
  208.                  > link file2+file1
  209.  
  210.              Here's the listing:
  211.  
  212.  
  213.                   Start  Stop   Length Name                   Class
  214.                   00000H 0018FH 00190H STACKSEG               STACK
  215.                   00190H 00191H 00002H NOTDATASTUFF           DATA
  216.                   001A0H 001B1H 00012H DATASTUFF              DATA
  217.                   001C0H 001C1H 00002H EVENMORESTUFF          DATA
  218.                   001D0H 001D1H 00002H MORESTUFF              DATA
  219.                   001E0H 001E1H 00002H EVENMORESTUFF          DATA
  220.                   001F0H 00201H 00012H MORESTUFFA             
  221.                   00210H 00211H 00002H MORESTUFF              CLASSOF68
  222.                   00220H 00234H 00015H CODESTUFF              CODE
  223.  
  224.                  Program entry point at 0022:0010
  225.  
  226.              Assure yourself that this is the order the classes are
  227.              encountered for file2+file1.
  228.  
  229.  
  230.              Before we go on, let's summarize what we have so far. 
  231.  
  232.                  1) In an .asm file, each segment starts with a name followed
  233.                  by the word SEGMENT.
  234.  
  235.                  2) Each segment ends with the name followed by the word ENDS
  236.                  (end of segment).
  237.  
  238.              This is the minimal segment definition:
  239.  
  240.                  ; - - - - - 
  241.                  SEG_A  SEGMENT
  242.  
  243.                  SEG_A  ENDS
  244.                  ; - - - - -
  245.  
  246.              In addition, if you want to combine a segment with segments from
  247.              other files in order to make one large segment, then all the
  248.              segments to be combined must:
  249.  
  250.                  1) have the same name.
  251.                  2) have the same class name (type)
  252.                  3) be declared PUBLIC
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.              Chapter 10 - Templates                                         93
  261.              ______________________
  262.  
  263.              ASSUME
  264.  
  265.              The next thing from the template file is the word ASSUME. Who is
  266.              assuming what?
  267.  
  268.                  ASSUME cs:CODESTUFF, ds:DATASTUFF
  269.  
  270.              This is for the assembler. It says that whenever you are working
  271.              in the CODESTUFF segment, CS will be set to the segment address
  272.              of the CODESTUFF segment. Whenever you are working in the
  273.              DATASTUFF segment, DS will be set to the segment address of the
  274.              DATASTUFF segment. The CS register takes care of itself, but it
  275.              is your responsibility to make sure that DS actually points to
  276.              the proper segment. 
  277.  
  278.  
  279.              If you just move a word from memory to a register:
  280.  
  281.                  mov  cx, variable1
  282.  
  283.              the 8086 automatically thinks that it is in the DS segment. But
  284.              it doesn't have to be that way. The 8086 has something called
  285.              segment overrides. Here is the list:
  286.  
  287.                          SEGMENT       HEX VALUE
  288.                            CS             2E
  289.                            DS             3E
  290.                            ES             26
  291.                            SS             36
  292.  
  293.              An override is a 1 byte machine instruction that tells the 8086
  294.              that for the next instruction, the memory location will not
  295.              reference the natural segment register; what it will reference is
  296.              the segment register named in the override - CS if it is 2Eh, DS
  297.              if it is 3Eh, ES if it is 26h, and SS if it is 36h. 
  298.  
  299.              We could plug these in ourselves, but that is a lot of work.
  300.              Fortunately, the assembler takes care of this for us. Let's look
  301.              at the code from the very beginning of the chapter.
  302.  
  303.              ;*********************************** 
  304.              ; segs.asm 
  305.               
  306.              ; - - - - - - - - - - - - - 
  307.              STACKSEG SEGMENT STACK  'STACK' 
  308.               
  309.              variable4dw   4444h
  310.                        dw     100h dup (?) 
  311.               
  312.              STACKSEG  ENDS 
  313.              ; - - - - - - - - - - - - - 
  314.              MORESTUFF SEGMENT PUBLIC  'HOKUM' 
  315.               
  316.              variable2    dw   2222h 
  317.               
  318.              MORESTUFF    ENDS 
  319.              ; - - - - - - - - - - - - -  
  320.  
  321.  
  322.  
  323.  
  324.              The PC Assembler Tutor                                         94
  325.              ______________________
  326.  
  327.              DATASTUFF  SEGMENT PUBLIC  'DATA' 
  328.               
  329.              variable1    dw     1111h 
  330.               
  331.              DATASTUFF    ENDS 
  332.              ; - - - - - - - - - - - - - 
  333.              CODESTUFF SEGMENT PUBLIC  'CODE' 
  334.               
  335.               EXTRN  print_num:NEAR , get_num:NEAR  
  336.               
  337.               ASSUME cs:CODESTUFF,ds:DATASTUFF 
  338.               ASSUME es:MORESTUFF,ss:STACKSEG 
  339.               
  340.              variable3    dw     3333h 
  341.  
  342.              main   proc far 
  343.              start: push  ds    
  344.                     sub   ax,ax 
  345.                     push  ax 
  346.               
  347.                     mov   ax, DATASTUFF 
  348.                     mov   ds,ax 
  349.                     mov   ax, MORESTUFF
  350.                     mov   es, ax
  351.               
  352.                     mov   cx, variable1 
  353.                     mov   variable1, cx 
  354.               
  355.                     ret 
  356.               
  357.              main   endp 
  358.               
  359.               
  360.              CODESTUFF    ENDS 
  361.              ; - - - - - - - - - - - -  
  362.               
  363.                  END     start 
  364.              ;***************************
  365.  
  366.              For the ASSUME statement we have:
  367.  
  368.               ASSUME cs:CODESTUFF,ds:DATASTUFF 
  369.               ASSUME es:MORESTUFF,ss:STACKSEG 
  370.  
  371.              What we want to look at is this section of code:
  372.  
  373.                  mov  cx, variable1
  374.                  mov  variable1, cx
  375.  
  376.              Here is the listing of the offset address and machine code:
  377.  
  378.  
  379.                 000E  8E C0                 mov   es,ax 
  380.                             
  381.                 0010  8B 0E 0000 R          mov   cx, variable1 
  382.                 0014  89 0E 0000 R          mov   variable1, cx 
  383.                                  
  384.  
  385.  
  386.  
  387.  
  388.              Chapter 10 - Templates                                         95
  389.              ______________________
  390.  
  391.                 0018  CB                    ret 
  392.  
  393.              Variable1 is in DATASTUFF (ASSUME ds:DATASTUFF), and DS is the
  394.              natural segment for variables. Now let's change the code to:
  395.  
  396.                  mov  cx, variable2
  397.                  mov  variable2, cx
  398.  
  399.              This is the ONLY change in the file. Variable2 is in MORESTUFF
  400.              and we have - ASSUME es:MORESTUFF.  Here's the listing when we
  401.              assemble the modified file.
  402.  
  403.                 000E  8E C0                  mov   es,ax 
  404.  
  405.                 0010  26: 8B 0E 0000 R       mov   cx, variable2 
  406.                 0015  26: 89 0E 0000 R       mov   variable2, cx 
  407.               
  408.                 001A  CB                     ret 
  409.               
  410.              The assembler has put 26h as a segment override. When the 8086
  411.              looks at the machine code, it knows that those two instructions
  412.              reference the es, not the ds, segment register. Also note that
  413.              the code is now two bytes longer - one byte for each segment
  414.              override. The "ret" instruction is at 1Ah (26d) instead of 18h
  415.              (24d).
  416.  
  417.              Let's try it with:
  418.  
  419.                  mov  cx, variable3
  420.                  mov  variable3, cx
  421.  
  422.              Variable3 is in CODESTUFF and we have - ASSUME cs:CODESTUFF.
  423.              Here's the listing:
  424.  
  425.                 000E  8E C0                  mov   es,ax 
  426.               
  427.                 0010  2E: 8B 0E 0000 R       mov   cx, variable3 
  428.                 0015  2E: 89 0E 0000 R       mov   variable3, cx 
  429.               
  430.                 001A  CB                     ret 
  431.               
  432.              The assembler put in the CS segment override. Now the 8086 knows
  433.              that variable3 is in the CS segment. Finally:
  434.  
  435.                  mov  cx, varaible4
  436.                  mov  variable4, cx
  437.  
  438.              Variable4 is in STACKSEG and we have - ASSUME ss:STACKSEG. Here's
  439.              the listing:
  440.  
  441.                 000E  8E C0                  mov   es,ax 
  442.  
  443.                 0010  36: 8B 0E 0000 R       mov   cx, variable4 
  444.                 0015  36: 89 0E 0000 R       mov   variable4, cx 
  445.  
  446.                 001A  CB                     ret 
  447.  
  448.  
  449.  
  450.  
  451.  
  452.              The PC Assembler Tutor                                         96
  453.              ______________________
  454.  
  455.              Once again, the assembler put in a segment override. This time it
  456.              was the SS override.
  457.  
  458.              That's nifty. We simply tell the assembler which segment register
  459.              we will use for each segment and it does all the work. We will do
  460.              more with segment overrides in the chapter on addressing modes.
  461.  
  462.              Remember, though, that it is your responsibility to see that at
  463.              the time this code is used, the segment register actually
  464.              contains the appropriate segment address.
  465.  
  466.              Is this ASSUME definition unique? That is, must there be a one to
  467.              one correspondence between segments and registers, with each
  468.              segment having its own register? No, not at all. Here are a two
  469.              ASSUME statements, both of which are legal:
  470.  
  471.                  ASSUME cs:COMSEG, ds:COMSEG, es:COMSEG, SS:COMSEG
  472.  
  473.              All four registers contain the address of the same segment. In
  474.              fact, we will meet this statement when we talk about COM files.
  475.              This is the only appropriate statement for a .COM file
  476.  
  477.                  ASSUME  ds:SEG_A, ds:SEG_B, es:SEG_C, es:SEG_D, es:SEG_A
  478.  
  479.              Four different segments, two of which are referenced by DS and
  480.              three of which are referenced by ES. Remember, ASSUME tells the
  481.              assembler that whenever you access something in that segment, the
  482.              named register will be set to the starting segment address. What
  483.              exactly does this mean to the assembler? Let's rearrange this a
  484.              little:
  485.  
  486.                  SEG_A     ds, es
  487.                  SEG_B     ds
  488.                  SEG_C     es
  489.                  SEG_D     es
  490.  
  491.              This is the list from the assembler's viewpoint. Suppose it has a
  492.              variable that is in SEG_C. Does it need an override? Yes, it
  493.              needs an ES override.  Suppose it has a variable in SEG_A. Does
  494.              it need an override? No, because DS is set to that segment. 
  495.  
  496.  
  497.  
  498.              SUBROUTINES
  499.  
  500.              In assembler parlance, subroutines are called procedures. Why?
  501.              You got me. In any case, whenever I say subroutine, process,
  502.              subprogram, or anything like that, I mean a procedure. A
  503.              procedure can have any name you want. You start a procedure by
  504.              giving the name, using the reserved word 'proc' and then 
  505.              defining it as either near or far. 
  506.  
  507.                  my_procedure  proc  near
  508.  
  509.              is a near procedure with the name my_procedure. You end a
  510.              procedure by giving the name and following it with the reserved
  511.              word 'endp' (for end of procedure).
  512.  
  513.  
  514.  
  515.  
  516.              Chapter 10 - Templates                                         97
  517.              ______________________
  518.  
  519.  
  520.                  my_procedure  endp
  521.  
  522.              What is a near procedure? It is one which is ALWAYS in the same
  523.              segment as the calling program. When you call a near procedure,
  524.              the value in CS stays the same, but IP (the instruction pointer)
  525.              changes to the offset of the first byte of the procedure. The
  526.              next instruction executed will be the first byte of the
  527.              procedure. 
  528.  
  529.              If a procedure is called even once from a different segment, then
  530.              it MUST be a far procedure.
  531.  
  532.                  my_procedure  proc  far
  533.  
  534.                  my_procedure  endp
  535.  
  536.              When you call a far procedure, the CS register is changed to the
  537.              segment of the called procedure and IP (the instruction pointer)
  538.              is set to the first byte of the procedure. This will be covered
  539.              in the chapter on subroutines. 
  540.  
  541.              How does the loader know where to start the program? The
  542.              assembler tells the linker which tells the loader. How does the
  543.              assembler know? You tell it. The last line of the file is the
  544.              single word 'END'. That tells the assembler that you are done
  545.              with the assembler code. If there is a word after the word 'END'
  546.              (on the same line), then the assembler assumes that this word is
  547.              the name of the label where the program starts. The first
  548.              instruction executed will be whatever immediately follows that
  549.              label. In the template files we have:
  550.  
  551.                  END start
  552.  
  553.              so the label 'start:' indicates where the first instruction is.
  554.              For an .EXE file, this can be anywhere at all, but we have it at
  555.              the beginning. The label 'start:' is used for clarity, but we
  556.              could just as easily have had:
  557.  
  558.                  END zzyx4
  559.  
  560.              The assembler would then look for the label 'zzyx4:' as the place
  561.              to start the program. If you look at the link .MAP file from our
  562.              file1+file2 example you will see:
  563.  
  564.                  Program entry point at 0021:0000 
  565.  
  566.              That says that the starting address is CS = 0021h, IP = 0000h.
  567.              Note that both CS and IP are different for the file2+file1
  568.              example:
  569.  
  570.                  Program entry point at 0022:0010
  571.  
  572.              where CS = 0022h  and IP = 0010h. The initial offset was given to
  573.              the linker by the assembler. The linker did any adjustment to the
  574.              offset if it moved the code, and then it calculated the segment
  575.              address itself.  
  576.  
  577.  
  578.  
  579.  
  580.              The PC Assembler Tutor                                         98
  581.              ______________________
  582.  
  583.  
  584.  
  585.              RET
  586.  
  587.              When the loader loads the program, it puts the segment of the
  588.              starting address in CS and the offset of the starting address in
  589.              IP. This gives control to your program. When your program is
  590.              done, how does it get back to the operating system? Good
  591.              question.
  592.  
  593.              When the loader loads the program, it creates something called
  594.              the PSP (program segment prefix). This is a 100h (256d) byte
  595.              block of information and code. The first byte (offset 0000) of
  596.              this block is an 8086 instruction for an orderly exit from a
  597.              program. What we need to do is set CS to the PSP segment and set
  598.              IP to 0000. Then the next instruction executed will be the
  599.              orderly exit code. 
  600.  
  601.              In talking about procedures, I said that when you call a far
  602.              procedure, the 8086 puts the procedure's segment in CS and the
  603.              procedure's offset in IP. But before that, it does two things:
  604.  
  605.                  push CS        ; these are the old CS and IP
  606.                  push IP        ; this is not a real 8086 instruction {2}
  607.  
  608.              When you have a RET (return) instruction in a far procedure, the
  609.              8086 does the following:
  610.  
  611.                  pop  IP        ; this is not a real 8086 instruction
  612.                  pop  CS        ; put back the old CS and IP
  613.  
  614.              so RET resets CS and IP to go back where it came from. That is
  615.              its job. 
  616.  
  617.              What has been pushed on the stack before starting your program?
  618.              NOTHING. That's right. That means that if you execute 
  619.  
  620.                  ret
  621.  
  622.              at the end of your program, the 8086 will pop two pieces of
  623.              garbage into IP and CS.
  624.  
  625.              Fortunately, when setting up a program, the loader ALWAYS puts
  626.              the segment address of the PSP in DS., the data segment. All we
  627.              need to do is PUSH DS (the PSP) and then PUSH 0 (offset 0000) and
  628.              we have the address of our orderly exit code. If we then execute
  629.              RET, it will POP these two items into IP and CS, sending us to
  630.              our orderly exit code. That is what is at the beginning of the
  631.              code section of the template file. We cannot PUSH a constant, so
  632.              we manufacture a 0 with 'sub ax, ax'. The code is:
  633.  
  634.                  push ds        ; PSP segment
  635.                  sub  ax, ax    ; manufacture a 0
  636.              ____________________
  637.  
  638.                 2 This is not actual 8086 code. You have no direct access to
  639.              IP. This is, however, what the 8086 effectively does.
  640.  
  641.  
  642.  
  643.  
  644.              Chapter 10 - Templates                                         99
  645.              ______________________
  646.  
  647.                  push ax        ; offset = 0000
  648.  
  649.              and the program is set up for the return. 
  650.  
  651.              That's a lot of things together, so let's review. To exit a
  652.              procedure we use RET, but for the starting procedure we need to
  653.              return to the operating system. The PSP has the code for an
  654.              orderly return at offset 0000. At load time, the loader puts the
  655.              segment address of the PSP in DS. We push the PSP segment address
  656.              and offset 0000 for later use by the RET instruction. We do this
  657.              with:
  658.  
  659.                  push ds        ; PSP segment
  660.                  sub  ax, ax    ; manufacture a 0
  661.                  push ax        ; offset = 0000
  662.  
  663.              These should be the first instructions in the program. 
  664.  
  665.              Now that you have stored the PSP, DS is free for other use. You
  666.              can now use DS to hold the segment address of your data. DS is
  667.              used because that is the segment register that the 8086 expects
  668.              unless told otherwise. You can't move a constant to a segment
  669.              register, so this is a two step process:
  670.  
  671.                  mov  ax, DATASTUFF
  672.                  mov  ds, ax
  673.  
  674.  
  675.              EXTRN
  676.  
  677.              Finally, an EXTRN statement tells the assembler that the
  678.              procedure or data is in another file and you did not forget it.
  679.              For a procedure, you need to say whether it is NEAR (push old IP
  680.              and put in new IP) or far (push old CS and IP; put in new CS and
  681.              IP). Here is the assembler listing for five calls:
  682.  
  683.                     E8 09CA R            call  near_routine 
  684.                     9A 15EE ---- R       call  far_routine 
  685.                     E8 0000 E            call  near_external_routine 
  686.                     9A 0000 ---- E       call  far_external_routine 
  687.                     E8 0000 E            call  get_unsigned 
  688.  
  689.              The first two are in the same file, the next two are in an
  690.              external file, and we have our friend 'get_unsigned'. 'R' means
  691.              that the data may be changed, 'E' means that it is external, and
  692.              will be done by the linker. The first four are labelled whether
  693.              they are near or far. 'get_unsigned' is a near procedure. Notice
  694.              that E8 is the near call while 9A is the far call. Also notice
  695.              that the assembler reserves one word for the new IP in the near
  696.              calls. If the call is in the same file, the assembler fills in
  697.              this number, but if it is external the assembler sets it to 0. In
  698.              the far calls the assembler reserves two words instead of one.
  699.              The first word is again the new IP, which is either filled in or
  700.              set to zero. The second word is for the segment address, and will
  701.              be set by the linker.
  702.               
  703.  
  704.  
  705.  
  706.  
  707.  
  708.              The PC Assembler Tutor                                        100
  709.              ______________________
  710.  
  711.              Whew!!! It sure took a long time to go through all that and you
  712.              still probably are unsure about some of this. Read the summary,
  713.              and if you don't feel good about it, leave it for a day or two
  714.              and reread it then.
  715.  
  716.              At the end of the book I will show you how you can simplify a lot
  717.              of these things by using standardized segment names and some
  718.              other standardized instructions. For now, you need to get used to
  719.              what the structure of programs is, and we will continue using the
  720.              same type of templates.{3}
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.  
  733.  
  734.  
  735.  
  736.  
  737.  
  738.  
  739.  
  740.  
  741.  
  742.  
  743.  
  744.  
  745.  
  746.  
  747.  
  748.  
  749.  
  750.  
  751.  
  752.  
  753.  
  754.  
  755.  
  756.  
  757.  
  758.  
  759.  
  760.  
  761.  
  762.              ____________________
  763.  
  764.                 3 Just think of me as the computer equivalent of a woodshop
  765.              teacher who forces you to use hand tools to make a coffee table
  766.              rather than allowing you to use what you really want to be
  767.              using - a chainsaw.
  768.  
  769.  
  770.  
  771.  
  772.              Chapter 10 - Templates                                        101
  773.              ______________________
  774.  
  775.  
  776.                                         SUMMARY
  777.  
  778.              SEGMENTS
  779.  
  780.              Segments are defined by giving a name followed by the word
  781.              SEGMENT. The end of a segment is signalled by the segment name,
  782.              followed by the word ENDS (end of segment).
  783.  
  784.                  ; - - - - -
  785.                  SOME_NAME  SEGMENT
  786.  
  787.                  SOME_NAME   ENDS
  788.                  ; - - - - -
  789.  
  790.              (As always, anything after a comma is a comment and is ignored by
  791.              the assembler). In addition, if you want to combine a segment
  792.              with other segments, then all the segments to be combined must:
  793.  
  794.                  1) have the same name.
  795.                  2) have the same type (class)
  796.                  3) be declared PUBLIC
  797.  
  798.  
  799.              THE STACK SEGMENT
  800.  
  801.              The stack segment may have any name you want, but should be
  802.              declared " SEGMENT  STACK 'STACK' ". This forces the loader to do
  803.              certain initialization for you. If you don't declare it this way,
  804.              you have to do the initialization yourself.
  805.  
  806.                  ANY_NAME  SEGMENT  STACK  'STACK'
  807.  
  808.  
  809.              EXTRN
  810.  
  811.              For procedures, an EXTRN statement tells the assembler that the
  812.              procedure that you want to call is in a different file, that you
  813.              didn't forget it. Procedures which are EXTRN must be declared
  814.              either NEAR or FAR. The grammar is name colon NEAR or name colon
  815.              FAR.
  816.  
  817.                  EXTRN     procedure1:NEAR, procedure2:FAR
  818.  
  819.              You may declare as many things on one line as will fit, but you
  820.              need to separate them with commas. There can be no comma at the
  821.              end. 
  822.  
  823.  
  824.              ASSUME
  825.  
  826.              An ASSUME statement tells the assembler that when a statement
  827.              references that particular segment, the corresponding segment
  828.              register will be set to that segment address.
  829.  
  830.                  ASSUME    es:MORESTUFF
  831.  
  832.  
  833.  
  834.  
  835.  
  836.              The PC Assembler Tutor                                        102
  837.              ______________________
  838.  
  839.              tells the assembler that no matter what you do in other parts of
  840.              the program, every time a variable in MORESTUFF is referenced, es
  841.              will have the segment address of MORESTUFF. This is for the
  842.              purpose of correct coding of segment overrides.
  843.  
  844.  
  845.              SEGMENT OVERRIDES
  846.  
  847.              Normally, when the 8086 accesses a variable in memory, it does so
  848.              via the DS segment register. This can be changed with a segment
  849.              override. The assembler puts the correct segment override code in
  850.              front of the instruction and the 8086 will use that segment
  851.              register to access the data in memory. The override codes are:
  852.  
  853.                          SEGMENT       HEX VALUE
  854.                            CS             2E
  855.                            DS             3E
  856.                            ES             26
  857.                            SS             36
  858.  
  859.  
  860.              CS
  861.  
  862.              CS is the code segment. When the 8086 processes machine code, it
  863.              ALWAYS uses CS. There is no override.
  864.  
  865.  
  866.              IP
  867.  
  868.              IP, the instruction pointer, gives the offset in CS of the next
  869.              instruction to be processed. When the 8086 processes an
  870.              instruction, it looks at IP, gets the next instruction and
  871.              updates IP. This is totally automatic and internal to the 8086.
  872.              You have no direct access to IP.
  873.  
  874.  
  875.              PROCEDURES
  876.  
  877.              A procedure is declared by giving a name followed by the word
  878.              'proc' followed by either NEAR or FAR. A procedure is ended by
  879.              giving the name, followed by 'endp' (end of procedure).
  880.  
  881.                  ; - - - - -
  882.                  square_root    proc far
  883.  
  884.                  square_root    endp
  885.                  ; - - - - -
  886.  
  887.              The words NEAR and FAR are for the assembler and the linker so
  888.              they know whether to change just IP or both IP and CS in RET, the
  889.              return statement as well as in CALL, the subroutine call.
  890.  
  891.  
  892.              RET
  893.  
  894.              The assembler codes a near or a far return depending on whether
  895.              you have declared a near or a far procedure. A NEAR return POPs
  896.  
  897.  
  898.  
  899.  
  900.              Chapter 10 - Templates                                        103
  901.              ______________________
  902.  
  903.              IP off of the stack while a FAR return POPs IP then POPs CS.
  904.              Thus, a NEAR return stays in the same segment but a FAR return
  905.              gets a new segment address in CS.{4} 
  906.  
  907.  
  908.              END
  909.  
  910.              The word END signals to the assembler that you are done with
  911.              code. The assembler will ignore all following lines, whether they
  912.              are blank or contain code.
  913.  
  914.              If the line with END  has a name after the word END, then the
  915.              assembler assumes that this is the name of a label where
  916.              execution will begin at run time. That means that the instruction
  917.              at 'label:' will be the first instruction executed in the
  918.              program.
  919.  
  920.  
  921.              SETUP
  922.  
  923.              In order to setup the program in the beginning you need to (1)
  924.              PUSH the segment address of the PSP (which is in DS), then push 0
  925.              (the offset of the orderly return code). Following this you need
  926.              to put the segment address of the data segment in DS. The code
  927.              for all of this is:
  928.  
  929.                  push ds             ; PSP seg address is in ds
  930.                  sub, ax, ax         ; 0
  931.                  push ax             ; push 0000 offset 
  932.  
  933.                  mov  ax, DATA_SEG   ; data segment address to ds
  934.                  mov  ds, ax
  935.  
  936.  
  937.  
  938.  
  939.  
  940.  
  941.  
  942.  
  943.  
  944.  
  945.  
  946.  
  947.  
  948.  
  949.  
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.              ____________________
  957.  
  958.                 4 Of course, it is possible for CS to keep the same value if
  959.              the calling procedure is is the same segment.
  960.  
  961.